<?php

/**
 * A class to maintain the DkpNormalizations and 
 * DkpStandings
 *
 */
class DkpUpdater
{
	
	public static $NORMALIZATION_FACTOR = 0.8;
	public static $NORMALIZARION_LIMIT = 200;
	
	public static $INITIAL_EARNED = 100;
	public static $INITIAL_SPENT = 100;
	
	/**
	 * Normalizes a user after the DateTime defined by time, if
	 * @param int 			characterId
	 * @param Date|null		time 
	 * @return bool
	 */
	public function normalizeUser($characterId, $dateTime = null){
		
		$userId = Characters::getById($characterId)->user_id;
		
		$dkpNormsTable = new DkpNormalizations();	
		

		//Removing all dkpNormalizations after time and that belongs to 
		//userId
		$selectNormDelete = $dkpNormsTable->select()
								->where('user_id = ?',$userId);
		if($dateTime != null){
			$selectNormDelete->where('time >= ?',$dateTime);
		}
		
		foreach ($dkpNormsTable->fetchAll($selectNormDelete) as $norms){
			$norms->delete();
		}
		
		//Finding latest normalization after delete
		$selectLatestNorm = $dkpNormsTable->select()
								->where('user_id = ?',$userId)
								->order('time DESC');
		$latestNormRow = $dkpNormsTable->fetchRow($selectLatestNorm);
		
		//Getting all dkpAdjustments for userId since the latestNorm, 
		//and all if no normalizations exist	

		$dkpAdjustmentsTable = new DkpAdjustments();
		$selectDkpAdj = $dkpAdjustmentsTable->select()
							->setIntegrityCheck(false)
							->from('dkp_adjustments')
							->join('dkp_adjustments_characters','dkp_adjustments_characters.dkp_adjustment_id = dkp_adjustments.id','character_id')
							->join('characters','characters.id = dkp_adjustments_characters.character_id','user_id')
							->where('characters.user_id = ?',$userId)
							->order('time ASC');
							
		//If a latest normalization exists, this is used as a steady state
		if($latestNormRow != null){
			$selectDkpAdj->where('time > ?',$latestNormRow->time);
		}					
							
		//echo $selectDkpAdj . '<br>'; //print the sql query
		
		$accEarned;
		$accSpent;

		//The earned and spent from the latest normalization is used as a steady state
		if($latestNormRow != null){
			$accEarned = $latestNormRow->earned;
			$accSpent = $latestNormRow->spent;
		} else { //no normalizations left
			$accEarned = self::$INITIAL_EARNED;
			$accSpent = self::$INITIAL_SPENT;
		}
		
		foreach($dkpAdjustmentsTable->fetchAll($selectDkpAdj) as $adj){
			$accEarned += $adj->dkp_earned;
			$accSpent += $adj->dkp_spent;
			
			//If the earned dkp passes the earned limit, a normalization is needed
			if ($accEarned >= self::$NORMALIZARION_LIMIT){
				
				$factor = self::$NORMALIZATION_FACTOR;
				$newEarned = $accEarned * $factor;
				$newSpent = $accSpent * $factor;				
				
				$data = array(	'user_id' 		=> $userId,
								'time'			=> $adj->time, //the time of the current entry
								'old_earned'	=> $accEarned,
								'old_spent'		=> $accSpent,
								'earned'		=> $newEarned,
								'spent'			=> $newSpent,
								'factor'		=> $factor
				);
				$dkpNormsTable->insert($data);
				
				//The loop continues with the normalized earned and spent
				$accEarned = $newEarned;
				$accSpent = $newSpent;
			}
		}
		
		//All adjustments have been iterated through, and the standings needs updated
		$standingData = array(	'user_id'	=> $userId,
								'earned'	=> $accEarned,
								'spent'		=> $accSpent,
								'buy_power'	=> $accEarned / $accSpent
						);
		
		$dkpStandingsTable = new DkpStandings();
		$selectStanding = $dkpStandingsTable->select()
							->where('user_id = ?',$userId);
		$standing = $dkpStandingsTable->fetchRow($selectStanding);		
		if($standing != null){
			$standing->setFromArray($standingData);
			$standing->save();
		} else {
			$dkpStandingsTable->insert($standingData);
		}		
	}
}

?>